﻿using EYangFrame.DataAccess.Global;
using EYangFramewirk.Business.SystemManager.Interfaces;
using EYangFramework.Common.Ninject;
using EYangFramework.CommonForm;
using EYangFramework.Domain.Entitys.Entrys;
using EYangFramework.Domain.Entitys.ValueObjects;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;

namespace EYangFramework.SystemManager
{
    public partial class frm_UserNavigationManager : EYangFramework.CommonForm.frm_BasicForm
    {
        //用于管理用户及角色的导航权限和菜单权限
        //菜单权限管理仅控制到继承自frm_BasicForm的窗体,是因为只有通过Ninject注入的窗体才能在创建的时候获取其菜单及权限
        UserObject currentUser { get; set; }
        AuthObject currentAuth { get; set; }
        List<User> currentUsers;
        List<Role> currentRoles;
        List<Navigation> currentNavigations;
        Dictionary<string, List<SubTool>> formMenus = null;//用于保存所有窗体的菜单,保证不用多次创建,提高效率,防止出错
        string selectNodeText;//用于保存选择的用户项目,防止在控件失去焦点的时候丢失
        public frm_UserNavigationManager()
        {
            currentUsers = null;
            currentRoles = null;
            InitializeComponent();
        }

        private void frm_UserNavigationManager_Load(object sender, EventArgs e)
        {
            this.Text = "权限管理";
            SetTabVisible(tp_Detail, false);
        }
        public override MenuStrip GetMenuMain()
        {
            return this.menuStrip1;
        }

        private void menuRoleNavigationAuth_Click(object sender, EventArgs e)
        {
            InitUser(UserObject.Role);
            currentAuth = AuthObject.Navigation;
            currentUser = UserObject.Role;
            InitAuth();
        }

        private void menuEditRoleMenuAuth_Click(object sender, EventArgs e)
        {
            InitUser(UserObject.Role);
            currentAuth = AuthObject.Menu;
            currentUser = UserObject.Role;
            InitAuth();
        }

        private void menuUserNavigationAuth_Click(object sender, EventArgs e)
        {
            InitUser(UserObject.User);
            currentAuth = AuthObject.Navigation;
            currentUser = UserObject.User;
            InitAuth();
        }

        private void menuEditUserMenuAuth_Click(object sender, EventArgs e)
        {
            InitUser(UserObject.User);
            currentAuth = AuthObject.Menu;
            currentUser = UserObject.User;
            InitAuth();
        }

        #region Auth操作
        private void InitAuth()
        {
            tree_Auth.Nodes.Clear();
            TreeNode treeRoot = new TreeNode();
            treeRoot.Text = "选择全部";
            tree_Auth.Nodes.Add(treeRoot);
            if (currentAuth == AuthObject.Menu)
            {
                if (formMenus == null)
                {
                    LoadFormMenus();
                }
                foreach (var form in formMenus)
                {
                    TreeNode treeNodeMain = new TreeNode();
                    treeNodeMain.Text = form.Key;
                    treeRoot.Nodes.Add(treeNodeMain);
                    ShowFormMenus(treeNodeMain, form.Value);
                }
            }
            else
            {
                if (currentNavigations == null)
                {
                    using (IBLLAuthManager authManager = NinjectProvider.NinjectCore.GetService<IBLLAuthManager>())
                    {
                        currentNavigations = authManager.GetAllNavigations();
                    }
                }
                ShowNavigation(treeRoot, currentNavigations.Where(t => t.PREVIEWNAVIGATION == null).ToList());
            }
            tree_Auth.ExpandAll();
        }
        private void ShowNavigation(TreeNode treeNode, List<Navigation> navigations)
        {
            foreach (var item in navigations)
            {
                TreeNode node = new TreeNode();
                node.Text = item.NAVIGATIONNAME;
                treeNode.Nodes.Add(node);
                if (currentNavigations.Any(t => t.PREVIEWNAVIGATION != null && t.PREVIEWNAVIGATION.ID == item.ID))
                {
                    ShowNavigation(node, currentNavigations.Where(t => t.PREVIEWNAVIGATION != null && t.PREVIEWNAVIGATION.ID == item.ID).ToList());
                }
            }
        }
        private void ShowFormMenus(TreeNode treeNode,List<SubTool> subTools)
        {
            foreach (var item in subTools)
            {
                TreeNode childNode = new TreeNode();
                childNode.Text = item.Text;
                childNode.Tag = item.Name + "/" + item.FormType;
                if (item.SubTools.Count > 0)
                {
                    ShowFormMenus(childNode, item.SubTools);
                }
                treeNode.Nodes.Add(childNode);
            }
        }
        private void LoadFormMenus()
        {
            formMenus = new Dictionary<string, List<SubTool>>();
            string[] fileInfos = Directory.GetFiles(Environment.CurrentDirectory, "*.dll");
            foreach (var item in fileInfos)
            {
                Assembly asm = Assembly.LoadFile(item);
                //获取所有的继承自frm_BasicForm的窗体,故权限只控制到继承自frm_BasicForm基窗体的窗体
                Type[] bllForms = asm.GetTypes().Where(t => t.IsPublic && !t.IsInterface && !t.IsAbstract && !t.IsGenericType && t.IsSubclassOf(typeof(frm_BasicForm))).OrderBy(t => t.Name).ToArray();
                foreach (var currentForm in bllForms)
                {
                    Object form = Activator.CreateInstance(currentForm);
                    var toolStrips = (form as frm_BasicForm).GetMenuMain() as ToolStrip;
                    if (toolStrips == null)
                    {
                        continue;
                    }
                    List<SubTool> tools = new List<SubTool>();
                    string formType = $"{currentForm.Assembly.GetName().Name}.{currentForm.Name}";
                    GetSubTool(toolStrips, tools, formType);
                    formMenus.Add(formType, tools);
                }
            }
        }
        //将窗体的菜单转换成树形结构
        private void GetSubTool(ToolStrip toolStrip,List<SubTool> subTools,string formType)
        {
            foreach (ToolStripMenuItem item in toolStrip.Items)
            {
                SubTool subTool = new SubTool();
                subTool.Text = item.Text;
                subTool.Name = item.Name;
                subTool.FormType = formType;
                if ((item as ToolStripDropDownItem).HasDropDownItems)
                {
                    GetSubToolDropDown(item, subTool.SubTools, formType);
                }
                subTools.Add(subTool);
            }
        }
        private void GetSubToolDropDown(ToolStripDropDownItem dropDownItem, List<SubTool> subTools, string formType)
        {
            foreach (ToolStripMenuItem item in dropDownItem.DropDownItems)
            {
                SubTool subTool = new SubTool();
                subTool.Text = item.Text;
                subTool.Name = item.Name;
                subTool.FormType = formType;
                if ((item as ToolStripDropDownItem).HasDropDownItems)
                {
                    GetSubToolDropDown(item, subTool.SubTools, formType);
                }
                subTools.Add(subTool);
            }
        }
        private void BindMenusChecked(TreeNode treeNode, List<Domain.Entitys.ValueObjects.Menu> menus)
        {
            foreach (TreeNode item in treeNode.Nodes)
            {
                if (menus.Any(t => t.FORMTYPE == item.Tag?.ToString().Split('/')[1] && t.MENUNAME == item.Tag?.ToString().Split('/')[0]))
                {
                    item.Checked = true;
                }
                else
                {
                    item.Checked = false;
                }
                if (item.Nodes.Count > 0)
                {
                    BindMenusChecked(item, menus);
                }
            }
        }
        private void BindNavigationsChecked(TreeNode treeNode, List<Navigation> navigations)
        {
            foreach (TreeNode item in treeNode.Nodes)
            {
                if (navigations.Any(t => t.NAVIGATIONNAME == item.Text))
                {
                    item.Checked = true;
                }
                else
                {
                    item.Checked = false;
                }
                if (item.Nodes.Count > 0)
                {
                    BindNavigationsChecked(item, navigations);
                }
            }
        }
        #endregion

        #region UserS操作
        private void InitUser(UserObject nextUser)
        {
            foreach (TreeNode item in tree_Auth.Nodes)
            {
                CancelAllNode(item);
            }
            if (nextUser == currentUser && (currentUsers != null && currentRoles != null))
            {
                return;
            }
            tree_User.Nodes.Clear();
            TreeNode treeMain = new TreeNode();
            if (nextUser == UserObject.User)
            {
                if (currentUsers == null)
                {
                    using (IBLLAuthManager authManager = NinjectProvider.NinjectCore.GetService<IBLLAuthManager>())
                    {
                        currentUsers = authManager.GetAllUsers();
                    }
                }
                treeMain.Text = "全部用户";
                treeMain.Tag = "All";
                tree_User.Nodes.Add(treeMain);
                ShowUsers(treeMain, currentUsers.Where(t => t.LEADER == null).ToList());
            }
            else
            {
                if (currentRoles == null)
                {
                    using (IBLLAuthManager authManager = NinjectProvider.NinjectCore.GetService<IBLLAuthManager>())
                    {
                        currentRoles = authManager.GetAllRoles();
                    }
                }
                treeMain.Text = "全部角色";
                treeMain.Tag = "All";
                tree_User.Nodes.Add(treeMain);
                ShowUsers(treeMain, currentRoles.Where(t => t.PARENT == null).ToList());
            }
            tree_User.ExpandAll();
        }
        private void ShowUsers<T>(TreeNode treeNode, List<T> childrens)
        {
            foreach (T t in childrens)
            {
                TreeNode currentNode = new TreeNode();
                if (t is User)
                {
                    currentNode.Text = (t as User).USERNAME;
                    if (currentUsers.Any(u => u.LEADER != null && u.LEADER.ID == (t as User).ID))
                    {
                        ShowUsers(currentNode, currentUsers.Where(u => u.LEADER != null && u.LEADER.ID == (t as User).ID).ToList());
                    }
                }
                else
                {
                    currentNode.Text = (t as Role).ROLENAME;
                    if (currentRoles.Any(r => r.PARENT != null && r.PARENT.ID == (t as Role).ID))
                    {
                        ShowUsers(currentNode, currentRoles.Where(r => r.PARENT != null && r.PARENT.ID == (t as Role).ID).ToList());
                    }
                }
                treeNode.Nodes.Add(currentNode);
            }
        }
        private void CancelAllNode(TreeNode treeNode)
        {
            foreach (TreeNode item in treeNode.Nodes)
            {
                item.Checked = false;
                if (item.Nodes.Count > 0)
                {
                    CancelAllNode(item);
                }
            }
        }
        #endregion

        #region 辅助枚举及内部类定义
        private enum UserObject
        {
            Role,
            User
        }
        private enum AuthObject
        {
            Navigation,
            Menu
        }
        private class SubTool
        {
            public string Text { get; set; }
            public string Name { get; set; }
            public string FormType { get; set; }
            public List<SubTool> SubTools = new List<SubTool>();
        }
        #endregion

        private void tree_User_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (tree_User.SelectedNode != null)
            {
                if (tree_User.SelectedNode.Parent == null)
                {
                    return;
                }
                selectNodeText = tree_User.SelectedNode.Text;
                label1.Text = $"你正在操作{selectNodeText}的权限!";
                if (currentAuth == AuthObject.Menu)
                {
                    //绑定已有的菜单权限
                    List<Domain.Entitys.ValueObjects.Menu> menus = new List<Domain.Entitys.ValueObjects.Menu>();
                    if (currentUser == UserObject.User)
                    {
                        //用户的权限不包含他所属角色的权限,这样的设计是为了避免角色权限被删除之后,用户仍然保留有仅角色拥有的权限
                        //通常情况下,非异常情况,用户的权限和所在角色的权限应该完全相同
                        menus = currentUsers.Where(t => t.USERNAME == selectNodeText).First().MENUS.ToList();
                    }
                    else
                    {
                        menus = currentRoles.Where(t => t.ROLENAME == selectNodeText).First().MENUS.ToList();
                    }
                    BindMenusChecked(tree_Auth.Nodes[0], menus);
                }
                else
                {
                    //绑定已有导航权限
                    List<Navigation> navigations = new List<Navigation>();
                    if (currentUser == UserObject.User)
                    {
                        navigations = currentUsers.Where(t => t.USERNAME == selectNodeText).First().NAVIGATIONS.ToList();
                    }
                    else
                    {
                        navigations = currentRoles.Where(t => t.ROLENAME == selectNodeText).First().NAVIGATIONS.ToList();
                    }
                    BindNavigationsChecked(tree_Auth.Nodes[0], navigations);
                }
            }
        }

        private void tree_Auth_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Action != TreeViewAction.ByMouse) return;//设置只有鼠标点击才有效,避免进入死循环
            foreach (TreeNode item in e.Node.Nodes)
            {
                item.Checked = e.Node.Checked;
            }
            if (e.Node.Parent == null)
            {
                return;
            }
            e.Node.Parent.Checked = false;
            foreach (TreeNode item in e.Node.Parent.Nodes)
            {
                if (item.Checked)
                {
                    e.Node.Parent.Checked = true;
                }
            }
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            using (IBLLAuthManager bLLAuthManager = NinjectProvider.NinjectCore.GetService<IBLLAuthManager>())
            {
                if (currentAuth == AuthObject.Menu)
                {
                    List<Domain.Entitys.ValueObjects.Menu> selectedMenus = new List<Domain.Entitys.ValueObjects.Menu>();
                    GetSelectedMenus(tree_Auth.Nodes[0], selectedMenus);
                    if (currentUser == UserObject.User)
                    {
                        bLLAuthManager.UpdatUserMenus(selectedMenus, selectNodeText);
                    }
                    else
                    {
                        bLLAuthManager.UpdateRoleMenus(selectedMenus, selectNodeText);
                    }
                }
                else
                {
                    List<Navigation> selectedNavigations = new List<Navigation>();
                    GetSelectedNavigations(tree_Auth.Nodes[0], selectedNavigations);
                    if (currentUser == UserObject.User)
                    {
                        bLLAuthManager.UpdateUserNavigations(selectedNavigations, selectNodeText);
                    }
                    else
                    {
                        bLLAuthManager.UpdateRoleNavigations(selectedNavigations, selectNodeText);
                    }
                }
                currentRoles = bLLAuthManager.GetAllRoles();
                currentUsers = bLLAuthManager.GetAllUsers();
            }
            MessageBox.Show("授权成功!");
        }

        #region 创建保存的权限清单
        private void GetSelectedMenus(TreeNode treeNode, List<Domain.Entitys.ValueObjects.Menu> menus)
        {
            foreach (TreeNode item in treeNode.Nodes)
            {
                if (item.Checked&&item.Parent.Parent!=null)
                {
                    menus.Add(new Domain.Entitys.ValueObjects.Menu()
                    {
                        MENUNAME = item.Tag.ToString().Split('/')[0],
                        FORMTYPE = item.Tag.ToString().Split('/')[1],
                        CREATEUSER = GlobalInfo.CurrentUser.USERNAME
                    });
                }
                if (item.Nodes.Count > 0)
                {
                    GetSelectedMenus(item, menus);
                }
            }
        }
        private void GetSelectedNavigations(TreeNode treeNode, List<Navigation> navigations)
        {
            foreach (TreeNode item in treeNode.Nodes)
            {
                if (item.Checked && item.Parent != null)
                {
                    navigations.Add(new Navigation()
                    {
                        NAVIGATIONNAME = item.Text,
                        CREATEUSER = GlobalInfo.CurrentUser.USERNAME
                    });
                }
                if (item.Nodes.Count > 0)
                {
                    GetSelectedNavigations(item, navigations);
                }
            }
        }
        #endregion
    }
}
